package com.leyou.sms.util;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.leyou.sms.config.SmsProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@EnableConfigurationProperties(SmsProperties.class)
public class SmsUtils {

    private static final String REDIS_KEY_PREFIX = "sms:phone:";
    private static final long SMS_MIN_INTERVAL_IN_MILLIS = 60000;

    @Resource
    private SmsProperties props;

    @Autowired
    private StringRedisTemplate redisTemplate;

    // 产品名称:云通信短信 API 产品,开发者无需替换
    private static final String PRODUCT_NAME = "Dysmsapi";
    // 产品域名,开发者无需替换
    private static final String DOMAIN_NAME = "dysmsapi.aliyuncs.com";

    /**
     * 验证码短信服务
     */
    public SendSmsResponse sendSms(String phoneNumber, String signName,
                                   String templateCode, String templateParam) {
        // 按手机号限流
        final String key = REDIS_KEY_PREFIX + phoneNumber;
        String lastTime = redisTemplate.opsForValue().get(key);

        //   1. 查看手机号是否已存在
        if (StringUtils.isNotBlank(lastTime)) {
            Long last = Long.valueOf(lastTime);
            //   2. 限流 / 放行
            if (System.currentTimeMillis() - last < SMS_MIN_INTERVAL_IN_MILLIS) {
                return null;
            }
        }



        try {
            // 可自助调整超时时间
            System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
            System.setProperty("sun.net.client.defaultReadTimeout", "10000");

            // 初始化 acsClient, 暂不支持 region 化
            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou",
                    props.getAccessKeyId(), props.getAccessKeySecret());
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", PRODUCT_NAME, DOMAIN_NAME);
            IAcsClient acsClient = new DefaultAcsClient(profile);

            // 组装请求对象-具体描述见控制台-文档部分内容
            SendSmsRequest request = new SendSmsRequest();
            request.setMethod(MethodType.POST);

            // 必填:待发送手机号
            request.setPhoneNumbers(phoneNumber);
            // 必填: 短信签名-可在短信控制台中找到
            request.setSignName(signName);
            // 必填: 短信模板-可在短信控制台中找到
            request.setTemplateCode(templateCode);
            // 可选: 模板中的变量替换 JSON 串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            request.setTemplateParam(templateParam);

            // hint 此处可能会抛出异常，注意 catch
            SendSmsResponse resp = acsClient.getAcsResponse(request);

            if (!"OK".equals(resp.getCode())) {
                log.error("[短信服务] 发送短信失败，phoneNumber：{}，原因：{}", phoneNumber, resp.getMessage());
            }

            // 发送短信成功，写入 Redis，指定生存时间 1 min
            redisTemplate.opsForValue().set(key,
                    String.valueOf(System.currentTimeMillis()), 1, TimeUnit.MINUTES);

            return resp;
        } catch (Exception e) {
            log.error("[短信服务] 发送短信异常，phoneNumber：{}", phoneNumber, e);
            return null;
        }
    }

}
